'''
Created on Jan 25, 2010

@author: madsk
'''

from __future__ import with_statement
from PIL import Image
from PyQt4 import QtCore
from imageops import *
import os
import logging
from scavenger import Scavenger
from scavenger_common import RemoteDataHandle

class Emitter(QtCore.QObject):
    started = QtCore.pyqtSignal(int)
    finished = QtCore.pyqtSignal(int, int)
    progress = QtCore.pyqtSignal(int, float, str)

    def __init__(self):
        super(Emitter, self).__init__()

class Task(QtCore.QRunnable):
    next_id = 0
    
    def __init__(self, image_path, operations):
        super(Task, self).__init__()
        self._image_path = str(image_path)
        self._operations = operations
        self._id = Task.next_id
        Task.next_id += 1
        self._emitter = Emitter() 
        
    def run(self):
        logger = logging.getLogger('Task')
        self.started.emit(self._id)
        
        # Load the image.
        try:
            with open(self._image_path, 'r') as infile:
                image = infile.read()
        except Exception, e:
            logger.error('Error reading input image.', exc_info=True)
            self.finished.emit(self._id, 1)
            return
        
        # Perform the operations on the image.
        opcount = 0
        for operation, args in self._operations:
            # Switch out depending on the operation.
            if operation == 'sharpen':
                try:
                    image = sharpen(image, *args)
                except Exception, e:
                    logger.error('Error performing sharpen operation.', exc_info=True)
                    self.finished.emit(self._id, -1)
                    return
                
            elif operation == 'blur':
                try:
                    image = blur(image, *args)
                except Exception, e:
                    logger.error('Error performing blur operation.', exc_info=True)
                    self.finished.emit(self._id, -2)
                    return

            elif operation == 'color':
                try:
                    image = color(image, *args)
                except Exception, e:
                    logger.error('Error performing color operation.', exc_info=True)
                    self.finished.emit(self._id, -3)
                    return

            elif operation == 'contrast':
                try:
                    image = contrast(image, *args)
                except Exception, e:
                    logger.error('Error performing contrast operation.', exc_info=True)
                    self.finished.emit(self._id, -4)
                    return

            elif operation == 'brightness':
                try:
                    image = brightness(image, *args)
                except Exception, e:
                    logger.error('Error performing brightness operation.', exc_info=True)
                    self.finished.emit(self._id, -5)
                    return

            elif operation == 'fliphorizontal':
                try:
                    image = fliphorizontal(image)
                except Exception, e:
                    logger.error('Error performing horizontal flip operation.', exc_info=True)
                    self.finished.emit(self._id, -6)
                    return

            elif operation == 'flipvertical':
                try:
                    image = flipvertical(image)
                except Exception, e:
                    logger.error('Error performing vertical flip operation.', exc_info=True)
                    self.finished.emit(self._id, -7)
                    return

            elif operation == 'scale':
                try:
                    image = scale(image, *args)
                except Exception, e:
                    logger.error('Error performing scale operation.', exc_info=True)
                    self.finished.emit(self._id, -8)
                    return

            opcount += 1
            self.progress.emit(self._id,float(opcount)/len(self._operations), operation)

        # Fetch result data if necessary.
        if type(image) == RemoteDataHandle:
            try:
                image = Scavenger.fetch_data(image)
            except Exception, e:
                logger.error('Error fetching remote data handle.', exc_info=True)

        # Save the result image and emit the 'finished' signal.
        rcode = self._saveImage(image)
        self.finished.emit(self._id, rcode)

    def _saveImage(self, image):
        logger = logging.getLogger('Task')

        # Make a backup of the original image.
        try:
            with open(self._image_path, 'r') as infile:
                with open(self._image_path + '.original', 'w') as outfile:
                    outfile.write(infile.read())
        except Exception, e:
            logger.error('Error making backup copy of image.', exc_info=True)
            return 2
        
        # Remove any old preview images.
        if os.path.exists(self._image_path + '.preview'):
            try:
                os.unlink(self._image_path + '.preview')
            except Exception, e:
                logger.error('Error removing preview image.', exc_info=True)
                return 3
        
        # Save the new image.
        try:
            with open(self._image_path, 'w') as outfile:
                outfile.write(image)
        except Exception, e:
            logger.error('Error saving image to "%s".'%self._image_path, exc_info=True)
            return 4
        
        # Return success.
        return 0
            
    def id(): #@NoSelf
        def fget(self):
            return self._id
        return locals()
    id = property(**id())
    
    def started(): #@NoSelf
        def fget(self):
            return self._emitter.started
        return locals()
    started = property(**started())

    def finished(): #@NoSelf
        def fget(self):
            return self._emitter.finished
        return locals()
    finished = property(**finished())

    def progress(): #@NoSelf
        def fget(self):
            return self._emitter.progress
        return locals()
    progress = property(**progress())
    